package com.chhuang.uresource.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.CharEncoding;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.chhuang.core.bean.QueryBean;
import com.chhuang.uresource.bean.UResourceQueryBean;
import com.chhuang.uresource.conts.SysConstants;
import com.chhuang.uresource.po.UResource;
import com.chhuang.uresource.service.IUResourceService;
import com.chhuang.utils.Assert;

@Controller
@RequestMapping("resource")
public class UResourceController {
	private static final Log log = LogFactory.getLog(UResourceController.class);
	
	@Autowired
	private IUResourceService resourceService;
	
	/**
	 * 分页查找
	 * @param search
	 * @param limit
	 * @param offset
	 * @param sort
	 * @param isDesc
	 * @param isOr
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value="/getList",method=RequestMethod.GET)
	public Object getList(String search, Integer limit, Integer offset, 
			String sort, Boolean isDesc, Boolean isOr) throws Exception{
		JSONObject json = new JSONObject();

		if(Assert.isValidString(search)){
			Pattern p = Pattern.compile("\\s+|\t+");
			Matcher m = p.matcher(search);
			search= m.replaceAll("%");
		}
		UResourceQueryBean resourceQueryBean = new UResourceQueryBean();
		resourceQueryBean.setResourceName(search);
		resourceQueryBean.setSearchKeyWords(search);
		resourceQueryBean.setResourceIntroduction(search);
		
		resourceQueryBean.setLimit(limit==null?10:limit);
		resourceQueryBean.setOffset(offset==null?0:offset);
		resourceQueryBean.setOr(isOr==null?true:isOr);
		resourceQueryBean.setSort(sort==null?"createTime":sort);
		resourceQueryBean.setDesc(isDesc==null?true:isDesc);
		
		QueryBean<UResource> queryBean = resourceService.seniorQuery(resourceQueryBean);
		
		json.put(SysConstants.Status.SUCCESS, true);
		json.put(SysConstants.Status.RESULT, queryBean);
		
		log.debug(json);
		return json;
	}
	
	/**
	 * 获取一条记录
	 * @param resourceId
	 * @return
	 * @throws Exception 
	 */
	@ResponseBody
	@RequestMapping(value="/getResource",method=RequestMethod.GET)
	public Object getResource(String resourceId) throws Exception {
		JSONObject json = new JSONObject();
		
		if(Assert.isValidString(resourceId)) {
			UResource resource = resourceService.findByPrimaryKey(resourceId);
			if(resource != null) {
				json.put(SysConstants.Status.SUCCESS, true);
				json.put(SysConstants.Status.RESULT, resource);
			}else {
				json.put(SysConstants.Status.SUCCESS, false);
				json.put(SysConstants.Status.RESULT, "资源不存在");
			}
		}else {
			json.put(SysConstants.Status.SUCCESS, false);
			json.put(SysConstants.Status.RESULT, "参数有误");
		}
		
		log.debug(json);
		return json;
	}

	/**
	 * 下载计数
	 * @param resourceId
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value="/downCount/{resourceId}", method=RequestMethod.GET)
	public Object downCount(@PathVariable("resourceId") String resourceId) throws Exception{
		JSONObject json = new JSONObject();
		
		if(Assert.isValidString(resourceId)){
    		UResource resource = resourceService.findByPrimaryKey(resourceId);
    		if(resource!=null && Assert.isValidString(resource.getResourcePath())) {
    			if(resource.getMaxReadNum()!=null && resource.getMaxReadNum()<=resource.getDownloadAmount()) {//上次的下载次数已经到了最大值，删除文件
    				resourceService.deleteByPrimaryKeys(new String[] {resourceId});
    			}else {//下载次数加1
	                Integer amount = resource.getDownloadAmount();
	                resource.setDownloadAmount(amount==null ? 1 : ++amount );
	                resourceService.update(resource);
					json.put(SysConstants.Status.SUCCESS, true);
				}
    		}else {
				json.put(SysConstants.Status.SUCCESS, false);
				json.put(SysConstants.Status.RESULT, "资源不存在");
			}
    	}else {
			json.put(SysConstants.Status.SUCCESS, false);
			json.put(SysConstants.Status.RESULT, "参数有误");
		}
		
		log.debug(json);
		return json;
	}
	
	/**
	 * 下载资源
	 * @param resourceId
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/download/{resourceId}", method=RequestMethod.GET)
    public String download(@PathVariable("resourceId") String resourceId) throws Exception{
		String path = "/WEB-INF/views/error/404.jsp";
    	if(Assert.isValidString(resourceId)){
    		UResource resource = resourceService.findByPrimaryKey(resourceId);
    		if(resource!=null && Assert.isValidString(resource.getResourcePath())) {
    			if(resource.getMaxReadNum()!=null && resource.getMaxReadNum()<=resource.getDownloadAmount()) {//上次的下载次数已经到了最大值，删除文件
    				resourceService.deleteByPrimaryKeys(new String[] {resourceId});
    			}else {
	    			File file = new File(resource.getResourcePath());
	    			if(file.exists()) {
		    			if(resource.getResourceLength() < 4194304) {//小于4M
		    				log.debug("下载 小 文件 ");
		    				path = "forward:/resource/down/"+resourceId;
		    			}else {//大于4M
		    				log.debug("下载 大 文件 ");
		    				path = "forward:/resource/downLargeRes/"+resourceId;
		    			}
		    			
		    			//下载次数加1
		                Integer amount = resource.getDownloadAmount();
		                resource.setDownloadAmount(amount==null ? 1 : ++amount );
		                resourceService.update(resource);
	    			}
    			}
    		}
    	}
    	return path;
    }

    
	/**
	 * 下载资源 文件过大时会内存溢出 FileUtils.readFileToByteArray(file)，一次性读取文件的，如果文件过大，可以考虑分批读取
	 * @param resourceId
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/down/{resourceId}", method=RequestMethod.GET)
    public ResponseEntity<byte[]> down(@PathVariable("resourceId") String resourceId) throws Exception{
    	ResponseEntity<byte[]> responseEntity = null;
    	if(Assert.isValidString(resourceId)){
    		UResource resource = resourceService.findByPrimaryKey(resourceId);
    		if(resource!=null && Assert.isValidString(resource.getResourcePath())) {
    			File file = new File(resource.getResourcePath());
    			if(file.exists()) {
	    			HttpHeaders headers = new HttpHeaders();
	    			String filename = resource.getResourceName();
	                headers.setContentDispositionFormData("attachment", URLEncoder.encode(filename, CharEncoding.UTF_8));
	                MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;
	                if(Assert.isValidString(resource.getResourceType())) {
	                	String types[] = resource.getResourceType().split("/");
	                	if(Assert.isValidArray(types) && types.length>1) {
	                		mediaType = new MediaType(types[0], types[1]);
	                	}
	                }
	                headers.setContentType(mediaType);
	                headers.setContentLength(resource.getResourceLength());
	                
	                //FileUtils.readFileToByteArray(file)，一次性读取文件的，如果文件过大，可以考虑分批读取
	                responseEntity = new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
	                log.debug("下载文件 : “" + resource.getResourceName() + "”");
    			}
    		}
    	}
    	return responseEntity;
    }
    
    
    /**
     * 下载资源，文件过大 分批读取
     * @param resourceId
     * @param request
     * @param response
     * @throws Exception
     */
	@ResponseBody
    @RequestMapping(value="/downLargeRes/{resourceId}", method=RequestMethod.GET)
    public void downLargeRes(@PathVariable("resourceId") String resourceId, HttpServletResponse response) throws Exception{
    	
    	if(Assert.isValidString(resourceId)){
    		UResource resource = resourceService.findByPrimaryKey(resourceId);
    		if(resource!=null && Assert.isValidString(resource.getResourcePath())) {
    			File file = new File(resource.getResourcePath());
    			if(file.exists()) {
    				InputStream fis = new BufferedInputStream(new FileInputStream(file));
    				response.reset();
    				if(Assert.isValidString(resource.getResourceType())) {
    					response.setContentType(resource.getResourceType());
    				}else {
    					response.setContentType("application/octet-stream");
    				}
	    			String filename = resource.getResourceName();
    				response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename, CharEncoding.UTF_8));
	    			response.setHeader("Content-Length",resource.getResourceLength().toString());
    				OutputStream outStream = new BufferedOutputStream(response.getOutputStream());
    				byte[] buffer = new byte[4194304];//4M
                    int i = -1;
                    while ((i = fis.read(buffer)) != -1) {
                    	outStream.write(buffer, 0, i);
                    }
                    outStream.flush();
                    outStream.close();
                    fis.close();
                    response.flushBuffer();
    				
    				log.debug("下载文件 : “" + resource.getResourceName() + "”");
    			}
    		}
    	}
    }
    
//	public static void main(String[] args) {
//		String str="hello	      	song";
//		Pattern p = Pattern.compile("\\s+|\t+");
//		Matcher m = p.matcher(str);
//		str= m.replaceAll("%");
//		System.out.println(str);
//	}
}
